package com.wang.luntan.common.util;

import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * redis的工具类
 * 里面全部存放json
 *
 * @author Wangsh
 */
@Log4j2
@Component("redisUtil")
public class RedisUtil {
    /* Rediskey的一些常量 */
    public static final String KEY_USERS_TOKEN = "users_token_";
    public static final String KEY_ADMINS_TOKEN = "admins_token_";

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 往redis里面放东西
     *
     * @param key       要合理规划
     * @param valueJSON json,里面必须包含创建时间
     * @return
     */
    public boolean put(final String key, final String valueJSON) {
        try {
            return (Boolean) this.redisTemplate.execute(new RedisCallback() {

                @Override
                public Object doInRedis(RedisConnection connection) throws DataAccessException {
                    byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
                    connection.set(keyByte, redisTemplate.getStringSerializer().serialize(valueJSON));
                    return true;
                }
            });
        } catch (Exception e) {
            log.error("从redis中存储数据报错了,键为:" + key, e);
        }
        return false;
    }


    /**
     * 往redis里面放东西
     *
     * @param key       要合理规划
     * @param valueJSON json,里面必须包含创建时间
     * @param timeout   过期时间,单位是秒
     * @return
     */
    public boolean put(final String key, final String valueJSON, final int timeout) {
        try {
            return (Boolean) this.redisTemplate.execute(new RedisCallback() {

                @Override
                public Object doInRedis(RedisConnection connection) throws DataAccessException {
                    byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
                    connection.set(keyByte, redisTemplate.getStringSerializer().serialize(valueJSON));
                    //设置一下过期时间
                    boolean flag = connection.expire(keyByte, timeout);
                    if (!flag) {
                        log.error(key + "--" + timeout + ",redis设置过时时间(毫秒)失败了--" + valueJSON);
                    }
                    return flag;
                }
            });
        } catch (Exception e) {
            log.error("从redis中存储数据报错了,键为:" + key, e);
        }
        return false;
    }

    /**
     * 往redis里面放东西
     *
     * @param key       要合理规划
     * @param valueJSON json,里面必须包含创建时间
     * @param expDate   旋转的是指定的日期过期
     * @return
     */
    public boolean put(final String key, final String valueJSON, final Date expDate) {
        try {
            return (Boolean) this.redisTemplate.execute(new RedisCallback() {

                @Override
                public Object doInRedis(RedisConnection connection) throws DataAccessException {
                    byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
                    connection.set(keyByte, redisTemplate.getStringSerializer().serialize(valueJSON));
                    //设置一下过期时间,单位是秒,所以要除上1000
                    boolean flag = connection.expireAt(keyByte, expDate.getTime() / 1000);
                    if (!flag) {
                        log.error(key + "--" + expDate.toLocaleString() + ",redis设置过时间点失败了--" + valueJSON);
                    }
                    return flag;
                }
            });
        } catch (Exception e) {
            log.error("从redis中存储数据报错了,键为:" + key, e);
        }
        return false;
    }

    /**
     * 从redis里面取数据
     *
     * @param key 会返回null
     * @return
     */
    public Object get(final String key) {
        try {
            return this.redisTemplate.execute(new RedisCallback() {

                @Override
                public Object doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
                    if (connection.exists(keyByte)) {
                        byte[] valueByte = connection.get(keyByte);
                        return redisTemplate.getStringSerializer().deserialize(valueByte);
                    }
                    return null;
                }
            });
        } catch (Exception e) {
            log.error("从redis中读取数据报错了,键为:" + key, e);
        }
        return null;
    }

    /**
     * 删除数据
     *
     * @param key
     * @return 返回删除的条数    -1 为键不存在
     */
    public boolean delete(final String key) {
        try {
            return (boolean) this.redisTemplate.execute(new RedisCallback() {

                @Override
                public Object doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
                    if (connection.exists(keyByte)) {
                        long keylon = connection.del(keyByte);
                        return true;
                    }
                    return false;
                }
            });
        } catch (Exception e) {
            log.error("从redis中删除数据报错了,键为:" + key, e);
        }
        return false;
    }

    /**
     * 角色授权
     */
    public boolean set(String key, String value) {
        log.info("---角色授权set---");
        /* 匿名类
         * 只要是new接口的,都是匿名类
         * */
        return (boolean) this.redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                /* RedisConnection
                 * key:是字节数组
                 * value:是字节数组;
                 *  */
                /* 将一个字符串,转换成二进制 */
                byte[] keyByte = redisTemplate.getDefaultSerializer().serialize(key);
                byte[] valueByte = redisTemplate.getDefaultSerializer().serialize(value);
                /* 返回值含义:
                 * true:保存成功
                 * false:表示保存失败 */
                return connection.set(keyByte, valueByte);
            }
        });
    }
}